with Ada.Text_Io;--*
use Ada.Text_Io;--*
with Raildefs, IO_Ports,Unsigned_Types,Dda06defs, Dda06defs.Dio,
   Dac_Controller, Controllers;
use Raildefs,Unsigned_Types, Dda06defs, Dda06defs.Dio,Dac_Controller,
   Controllers;
with Ada.Text_Io;
with Swindows;
use Swindows;
with Ada.Real_Time;
use Ada.Real_Time;


package body Hand_Controller is --CYCLIC

   --Cyclic period
   Period : constant Time_Span := Milliseconds (100);
   --Memory addresses
   PA    : constant                 := Base_Address + 12;
   PB    : constant                 := Base_Address + 13;
   PC    : constant                 := Base_Address + 14;
   PCTL  : constant                 := Base_Address + 15;
   W_Int :          Swindows.Window;

   Line_Number   : Natural := 1;
   Window_Length : Natural := 14;

   procedure Init_W_Int (
         Win : in     Swindows.Window) is
   begin
      W_Int:= Win;
   end Init_W_Int;

   --Task body
   task body Hand_Controller_Cyclic is

      type Controller_State_Array is array (Controller_Id) of Controller_State;
      Controller_States : Controller_State_Array;

      function Read_Dial (
            Hid : Controller_Id)
        return Dial_Value is
         Data    : Unsigned_8;
         CS_Data : CS_Register;
      begin
         CS_Data.Hid:=Natural(Hid)-1;--range is 0 to 2
         CS_Data.Eoc:=Off;
         IO_Ports.Write_IO_Port (CS, Unsigned(CS_Data));
         --Put_Line(W_int,"Io poRt hand held");
         IO_Ports.Write_IO_Port (AD_Hi,0);
         --Put_Line("Io poRt hand held");
         loop
            IO_Ports.Read_IO_Port (CS,Data);
            CS_Data:=CS_Register_Convert(Data);
            if CS_Data.Eoc= On then --finished conversion (1=buy 0=done)
               exit;
            end if;
         end loop;
         IO_Ports.Read_IO_Port (AD_Hi,Data);
         return Dial_Value(Data/4);--mask the 2 lsb
      end Read_Dial;

      function Read_Controller (
            Hid : Controller_Id)
        return Controller_State is
         Temp_State : Controller_State; --already initialised
         Data       : Register;
         Byte       : Unsigned_8;
      begin
         Temp_State.Dial:=Read_Dial(Hid);
         IO_Ports.Read_IO_Port (Reg_Addrs(Hid),Byte);
         --Put_Line(W_Int,"Add"&Reg_Addrs(Hid)'Img);
         -- Line_Number:= (Line_Number mod Window_Length) +1;

         --read controller vals
         Data:=Register_Convert(Byte);
         if Data.Horn=On then
            Temp_State.Horn:=True;
            --Put_Line(W_Int,"Horn Goood");
            -- Line_Number:= (Line_Number mod Window_Length) +1;

         end if;
         if Data.Halt=On then
            Temp_State.Halt:=True;
            -- Put_Line(W_Int,"Halt Goood");
            -- Line_Number:= (Line_Number mod Window_Length) +1;

         end if;
         if Data.Dir=On then
            Temp_State.Dir:=Rev;
            -- Put_Line(W_Int,"Rev Goood");
            --  Line_Number:= (Line_Number mod Window_Length) +1;

         end if;
         Temp_State.T_Pref:=Reg_To_Pref(Data.T_Pref);
         return Temp_State;
      end Read_Controller;


      procedure Update (
            Hid : Controller_Id) is
         Temp_State  : Controller_State;
         Temp_Number : Unsigned_8;
      begin
         --Put_Line(W_int,"Io poRt hand held");
         Temp_State:=Read_Controller(Hid);
         if Temp_State.Dial /= Controller_States(Hid).Dial then
            if Temp_State.Dial <32 then
               Controllers.Start_Halt(Hid);
               -- Dac_Controller.Set_Voltage(Cab_Type(Hid),0);
            else
               Temp_Number := Unsigned_8(Temp_State.Dial);
               Temp_Number := (Temp_Number - 32)*8;
               --Dac_Controller.Set_Voltage(Cab_Type(Hid),Temp_Number);		
               Controllers.Start_Train_Speed(
                  T_Id        => Hid,
                  Speed_Value => Temp_Number);
            end if;

         end if;
         if Temp_State.T_Pref /= Controller_States(Hid).T_Pref then
            if(Temp_State.T_Pref = Right) then
               Controllers.Start_Train_Direction_Right(Hid);
            end if;
            if(Temp_State.T_Pref = Left) then
               Controllers.Start_Train_Direction_Left(Hid);
            end if;

         end if;
         if Temp_State.Dir /= Controller_States(Hid).Dir then
            if(Temp_State.Dir = Fwd) then
               Controllers.Start_Train_Forward(Hid);
            end if;
            if(Temp_State.Dir = Rev) then
               Controllers.Start_Train_Backward(Hid);
            end if;

            --Direction_Message.Direction := Temp_State.Dir;
            --Push(Hid,Direction_Message);
         end if;
         if Temp_State.Horn /= Controller_States(Hid).Horn and
               Temp_State.Horn then
            --Not implementing
            null;
         end if;
         if Temp_State.Halt /= Controller_States(Hid).Halt and
               Temp_State.Halt then
            if(Temp_State.Halt = True) then
               Controllers.Start_Halt(Hid);
            else
               Controllers.Start_Fast(Hid);
            end if;
         end if;
         Controller_States(Hid):=Temp_State;
         Put_Line(W_Int,"V "&Temp_Number'Img&Temp_State.T_Pref'Img&Temp_State.Dir'Img&"H "&Temp_State.Halt'Img,Line_Number);
         Line_Number:= (Line_Number mod Window_Length) +1;
      end Update;

      Next_Time : Time := Clock;
   begin
      delay 6.0;
      IO_Ports.Write_IO_Port (Pctl_Addr, Pctl_Init2);--set up tristate
      loop
         delay until Next_Time;
         Line_Number := 1;
         for I in Controller_Id'range loop
            Update(I);
         end loop;
         Next_Time := Next_Time + Period;
      end loop;
   end Hand_Controller_Cyclic;

end Hand_Controller;
